#include "EventLoop.h"
#include"log.h"
#include"Channel.h"

// #include "EventLoop.h"
// #include "Logger.h"
// #include "Poller.h"
// #include "Channel.h"

// #include <sys/eventfd.h>
// #include <unistd.h>
// #include <fcntl.h>
// #include <errno.h>
// #include <memory>

__thread EventLoop *t_loopInThisThread = nullptr;

const int kPollTimeMs = 10000;

int createEventfd()
{
    int evtfd = ::eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (evtfd = 0)
    {
        LOG_FATAL("Event error code:%d", errno);
    }
    return evtfd;
}

EventLoop::EventLoop() : looping_(false), quit_(false), callingPendingFunctions_(false), threadId_(CurrentThread::tid()), poller_(Poller::newDefaultPoller(this)), wakeup_(createEventfd()), wakeupChannel_(new Channel(this, wakeup_))
{
    LOG_DEBUGER("EventLoop create %p,int thread %d\n", this, threadId_);
    if (t_loopInThisThread != nullptr)
    {
        LOG_FATAL("the Other EventLoop %p exists in %d", t_loopInThisThread, threadId_);
    }
    else
    {
        t_loopInThisThread = this;
    }
    //  设置wakeupfd事件类型以及发生后的回调操作
    wakeupChannel_->ReadCallBack(std::bind(&EventLoop::handleRead, this));
    // 每一个loop都i将监听wakeupchannel的epollin事件了
    wakeupChannel_->enableReading();
};
EventLoop::~EventLoop()
{
    wakeupChannel_->disableAll();
    wakeupChannel_->remove();
    ::close(wakeup_);
    t_loopInThisThread = nullptr;
};

void EventLoop::loop()
{
    looping_ = true;
    quit_ = false;
    LOG_INFO("EventLoop %p start loop\n", this);
    while (!quit_)
    {
        activeChannels_.clear();
        pollReturnTime_ = poller_->poll(kPollTimeMs, &activeChannels_);
        for (Channel *channel : activeChannels_)
        {
            // channel处理相应的事件
            channel->handlerEvevt(pollReturnTime_);
        }
        // 执行eventloop事件循环需要处理的回调操作
        doPendingFunctors();
    }
    LOG_INFO("EventLoop %p stop looping\n", this);
    looping_ = false;
};
void EventLoop::quit()
{
    // 如果是当前线程调用则quit与loop是同步的
    quit_ = true;
    if (!isInLoopThread())
    { // 如果是subloop调用mainloop则应该先使用wakeup来避免mianloop中的poll阻塞不跳出的情况。
        wakeup();
    }
};
// 在当前loop中执行cb
void EventLoop::runInLoop(Functor cb)
{
    if (isInLoopThread())
    {
        cb();
    }
    else
    {
        queueInLoop(cb);
    }
};
// 把cb放入队列中，唤醒loop所在的线程，执行cb
void EventLoop::queueInLoop(Functor cb)
{
    {
        std::unique_lock<std::mutex> lock(mutex_);
        pendingFunctors_.emplace_back(cb);
    }
    if (!isInLoopThread() || callingPendingFunctions_)
    // 如果当前loop正在处理回调，当处理完成后唤醒poll，再次处理，否则poll会阻塞但是已经有回调队列里有新的回调函数了。
    {
        wakeup();
    }
};

// 唤醒loop所在的线程
void EventLoop::wakeup()
{
    uint64_t one = 1;
    ssize_t n = write(wakeup_, &one, sizeof one);
    if (n != sizeof one)
    {
        LOG_ERROR("weakup() is write %lu bytes error \n", n);
    }
};
// poller中的方法
void EventLoop::updateChannel(Channel *channel)
{
    poller_->updateChannel(channel);
};
void EventLoop::removeChannel(Channel *channel)
{
    poller_->removeChannel(channel);
};
bool EventLoop::hasChannel(Channel *channel)
{
    return poller_->hasChannel(channel);
};


void EventLoop::handleRead()
{
    uint64_t one = 1;
    ssize_t n = read(wakeup_, &one, sizeof one);
    if (n != sizeof one)
    {
        LOG_ERROR("EventLoop::handler error %d", n);
    }

}; // 唤醒
void EventLoop::doPendingFunctors()
{
    std::vector<Functor> functors;
    callingPendingFunctions_ = true;
    {
        std::unique_lock<std::mutex> lock(mutex_);
        functors.swap(pendingFunctors_); // 在当前线程中调用临时构造的回调函数，不影响原本的回调队列被mainloop写入时阻塞。
    }
    for (auto fun : functors)
    {
        fun(); // 执行当前loop需要执行的回调操作
    }
    callingPendingFunctions_ = false;
}; // 执行函数列表回调
